how garbage collection work in java